package com.carl.leetcode.dp;

/**
 * Created by carlXie on 2016/1/8.
 * email: kkrimen@gmail.com
 */
public class RegularExpressionMatching {
    public static void main(String[] args) {
        System.out.println("aa, a : " + isMatch("aa", "a"));
        System.out.println("aa, aa : " + isMatch("aa", "aa"));
        System.out.println("aaa, aa : " + isMatch("aaa", "aa"));
        System.out.println("aaa, aaaa : " + isMatch("aaa", "aaaa"));
        System.out.println("aa, a* : " + isMatch("aa", "a*"));
        System.out.println("aa, .* :" + isMatch("aa", ".*"));
        System.out.println("ab, .* : " + isMatch("ab", ".*"));
        System.out.println("aab, c*a*b : " + isMatch("aab", "c*a*b"));

        System.out.println(", : " + isMatch("", ""));
        System.out.println("abcdeff, .* : " + isMatch("abcdeff", ".*"));
        System.out.println("aaa, a*a : " + isMatch("aaa", "a*a"));
        System.out.println("bb, .bab : " + isMatch("bb", ".bab"));
        System.out.println("bb, a*bbc* : " + isMatch("bb", "a*bbc*"));
        System.out.println("ad, d* : " + isMatch("ad", "d*"));
        System.out.println("aaa, ab*a : " + isMatch("aaa", "ab*a"));
    }

    /**
     */
    public static boolean isMatch(String s, String p) {
        int m = s.length(), n = p.length();
        boolean[][] dp = new boolean[m + 1][n + 1];
        dp[0][0] = true;
        for (int j = 1; j <= n; j++) {
            if (p.charAt(j - 1) != '*') dp[0][j] = false;
            else dp[0][j] = dp[0][j - 2];
        }

        for (int i = 1; i <= m; i++) {
            for (int j = 1; j <= n; j++) {
                if (p.charAt(j - 1) != '*') {
                    dp[i][j] = dp[i - 1][j - 1] && (s.charAt(i - 1) == p.charAt(j - 1) || p.charAt(j - 1) == '.');
                } else {
                    if (dp[i - 1][j] && (s.charAt(i - 1) == p.charAt(j - 2) || p.charAt(j - 2) == '.')) dp[i][j] = true;
                    else if (dp[i][j - 1] || dp[i][j - 2]) dp[i][j] = true;
                    else dp[i][j] = false;
                }
            }
        }

        return dp[m][n];
    }
}
